<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>6. 模块 &mdash; Python tutorial 3.4 documentation</title>
    
    <link rel="stylesheet" href="_static/default.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    './',
        VERSION:     '3.4',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="top" title="Python tutorial 3.4 documentation" href="index.html" />
    <link rel="next" title="7. 输入和输出" href="inputoutput.html" />
    <link rel="prev" title="5. 数据结构" href="datastructures.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="inputoutput.html" title="7. 输入和输出"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="datastructures.html" title="5. 数据结构"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Python tutorial 3.4 documentation</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="tut-modules">
<span id="id1"></span><h1>6. 模块<a class="headerlink" href="#tut-modules" title="Permalink to this headline">¶</a></h1>
<p>如果你退出 Python 解释器并重新进入，你做的任何定义（变量和方法）都会丢失。 因此，如果你想要编写一些更大的程序，为准备解释器输入使用一个文本编辑器会更好，并以那个文件替代作为输入执行。 这就是传说中的 <em>脚本</em> 。 随着你的程序变得越来越长，你可能想要将它分割成几个更易于维护的文件。 你也可能想在不同的程序中使用顺手的函数，而不是把代码在它们之间中拷来拷去。</p>
<p>为了满足这些需要，Python 提供了一个方法可以从文件中获取定义，在脚本或者解释器的一个交互式实例中使用。这样的文件被称为 <em>模块</em> ；模块中的定义可以 <em>导入</em> 到另一个模块或 <em>主模块</em> 中（在脚本执行时可以调用的变量集位于最高级，并且处于计算器模式）。</p>
<p>模块是包括 Python 定义和声明的文件。文件名就是模块名加上 <tt class="file docutils literal"><span class="pre">.py</span></tt>  后缀。模块的模块名（做为一个字符串）可以由全局变量 <tt class="docutils literal"><span class="pre">__name__</span></tt> 得到。例如，你可以用自己惯用的文件编辑器在当前目录下创建一个叫 fibo.py 的文件，录入如下内容:</p>
<div class="highlight-python"><div class="highlight"><pre># Fibonacci numbers module

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b &lt; n:
        print(b, end=&#39; &#39;)
        a, b = b, a+b
    print()

def fib2(n): # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while b &lt; n:
        result.append(b)
        a, b = b, a+b
    return result
</pre></div>
</div>
<p>现在进入 Python 解释器并使用以下命令导入这个模块:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span>
</pre></div>
</div>
<p>这样做不会直接把 <tt class="docutils literal"><span class="pre">fibo</span></tt> 中的函数导入当前的语义表；它只是引入了模块名 <tt class="docutils literal"><span class="pre">fibo</span></tt> 。你可以通过模块名按如下方式访问这个函数:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">fibo</span><span class="o">.</span><span class="n">fib</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="go">1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fibo</span><span class="o">.</span><span class="n">fib2</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="go">[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fibo</span><span class="o">.</span><span class="n">__name__</span>
<span class="go">&#39;fibo&#39;</span>
</pre></div>
</div>
<p>如果打算频繁使用一个函数，你可以将它赋予一个本地变量:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span> <span class="o">=</span> <span class="n">fibo</span><span class="o">.</span><span class="n">fib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<div class="section" id="tut-moremodules">
<span id="id2"></span><h2>6.1. 深入模块<a class="headerlink" href="#tut-moremodules" title="Permalink to this headline">¶</a></h2>
<p>除了包含函数定义外，模块也可以包含可执行语句。 这些语句一般用来初始化模块。 他们仅在 <em>第一次</em> 被导入的地方执行一次。 <a class="footnote-reference" href="#id11" id="id3">[1]</a></p>
<p>每个模块都有自己私有的符号表，被模块内所有的函数定义作为全局符号表使用。 因此，模块的作者可以在模块内部使用全局变量，而无需担心它与某个用户的全局变量意外冲突。 从另一个方面讲，如果你确切的知道自己在做什么，你可以使用引用模块函数的表示法访问模块的全局变量， <tt class="docutils literal"><span class="pre">modname.itemname</span></tt> 。</p>
<p>模块可以导入其他的模块。 一个（好的）习惯是将所有的 <tt class="xref std std-keyword docutils literal"><span class="pre">import</span></tt> 语句放在模块的开始（或者是脚本），这并非强制。 被导入的模块名会放入当前模块的全局符号表中。</p>
<p><tt class="xref std std-keyword docutils literal"><span class="pre">import</span></tt> 语句的一个变体直接从被导入的模块中导入命名到本模块的语义表中。例如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">fibo</span> <span class="kn">import</span> <span class="n">fib</span><span class="p">,</span> <span class="n">fib2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<p>这样不会从局域语义表中导入模块名（如上所示， <tt class="docutils literal"><span class="pre">fibo</span></tt> 没有定义）。</p>
<p>甚至有种方式可以导入模块中的所有定义:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">fibo</span> <span class="kn">import</span> <span class="o">*</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<p>这样可以导入所有除了以下划线( <tt class="docutils literal"><span class="pre">_</span></tt> )开头的命名。</p>
<p>需要注意的是在实践中往往不鼓励从一个模块或包中使用 <tt class="docutils literal"><span class="pre">*</span></tt> 导入所有，因为这样会让代码变得很难读。不过，在交互式会话中这样用很方便省力。</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">出于性能考虑，每个模块在每个解释器会话中只导入一遍。因此，如果你修改了你的模块，需要重启解释器——或者，如果你就是想交互式的测试这么一个模块，可以用 <tt class="xref py py-func docutils literal"><span class="pre">reload()</span></tt> 重新加载，例如 <tt class="docutils literal"><span class="pre">reload(modulename)</span></tt> 。</p>
</div>
<div class="section" id="tut-modulesasscripts">
<span id="id4"></span><h3>6.1.1. 作为脚本来执行模块<a class="headerlink" href="#tut-modulesasscripts" title="Permalink to this headline">¶</a></h3>
<p>当你使用以下方式运行 Python 模块时，模块中的代码便会被执行:</p>
<div class="highlight-python"><div class="highlight"><pre>python fibo.py &lt;arguments&gt;
</pre></div>
</div>
<p>模块中的代码会被执行，就像导入它一样，不过此时 <tt class="docutils literal"><span class="pre">__name__</span></tt> 被设置为 <tt class="docutils literal"><span class="pre">&quot;__main__&quot;</span></tt> 。这相当于，如果你在模块后加入如下代码:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="kn">import</span> <span class="nn">sys</span>
    <span class="n">fib</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
</pre></div>
</div>
<p>就可以让此文件像作为模块导入时一样作为脚本执行。此代码只有在模块作为 “main” 文件执行时才被调用:</p>
<div class="highlight-python"><div class="highlight"><pre>$ python fibo.py 50
1 1 2 3 5 8 13 21 34
</pre></div>
</div>
<p>如果模块被导入，不会执行这段代码:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>这通常用来为模块提供一个便于测试的用户接口（将模块作为脚本执行测试需求）。</p>
</div>
<div class="section" id="tut-searchpath">
<span id="id5"></span><h3>6.1.2. 模块的搜索路径<a class="headerlink" href="#tut-searchpath" title="Permalink to this headline">¶</a></h3>
<p id="index-0">导入一个叫 <tt class="xref py py-mod docutils literal"><span class="pre">spam</span></tt> 的模块时，解释器先在当前目录中搜索名为 <tt class="file docutils literal"><span class="pre">spam.py</span></tt>  的文件。如果没有找到的话，接着会到 <tt class="xref py py-data docutils literal"><span class="pre">sys.path</span></tt> 变量中给出的目录列表中查找。 <tt class="xref py py-data docutils literal"><span class="pre">sys.path</span></tt> 变量的初始值来自如下：</p>
<ul class="simple">
<li>输入脚本的目录（当前目录）。</li>
<li>环境变量 <span class="target" id="index-1"></span><tt class="xref std std-envvar docutils literal"><span class="pre">PYTHONPATH</span></tt> 表示的目录列表中搜索 (这和 shell 变量 <span class="target" id="index-2"></span><tt class="xref std std-envvar docutils literal"><span class="pre">PATH</span></tt> 具有一样的语法，即一系列目录名的列表)。</li>
<li>Python 默认安装路径中搜索。</li>
</ul>
<p>实际上，解释器由 <tt class="xref py py-data docutils literal"><span class="pre">sys.path</span></tt> 变量指定的路径目录搜索模块，该变量初始化时默认包含了输入脚本（或者当前目录）， <span class="target" id="index-3"></span><tt class="xref std std-envvar docutils literal"><span class="pre">PYTHONPATH</span></tt> 和安装目录。这样就允许 Python 程序了解如何修改或替换模块搜索目录。需要注意的是由于这些目录中包含有搜索路径中运行的脚本，所以这些脚本不应该和标准模块重名，否则在导入模块时 Python 会尝试把这些脚本当作模块来加载。这通常会引发错误。请参见 <a class="reference internal" href="#tut-standardmodules"><em>标准模块</em></a>  以了解更多的信息。</p>
</div>
<div class="section" id="python">
<h3>6.1.3. “编译的” Python 文件<a class="headerlink" href="#python" title="Permalink to this headline">¶</a></h3>
<p>对于引用了大量标准模块的短程序，有一个提高启动速度的重要方法，如果在 <tt class="file docutils literal"><span class="pre">spam.py</span></tt> 所在的目录下存在一个名为 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 的文件，它会被视为 <tt class="xref py py-mod docutils literal"><span class="pre">spam</span></tt> 模块的预“编译”（ <tt class="docutils literal"><span class="pre">byte-compiled</span></tt> ，二进制编译）版本。用于创建 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 的这一版 <tt class="file docutils literal"><span class="pre">spam.py</span></tt>  的修改时间记录在 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 文件中，如果两者不匹配，<tt class="file docutils literal"><span class="pre">.pyc</span></tt> 文件就被忽略。</p>
<p>通常你不需要为创建 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 文件做任何工作。一旦 <tt class="file docutils literal"><span class="pre">spam.py</span></tt> 成功编译，就会尝试生成对应版本的 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 。如果有任何原因导致写入不成功，生成的 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 文件就会视为无效，随后即被忽略。 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 文件的内容是平台独立的，所以 Python 模块目录可以在不同架构的机器之间共享。</p>
<p>部分高级技巧:</p>
<ul>
<li><p class="first">以 <em class="xref std std-option">-O</em> 参数调用 Python 解释器时，会生成优化代码并保存在 <tt class="file docutils literal"><span class="pre">.pyo</span></tt>  文件中。现在的优化器没有太多帮助；它只是删除了断言（ <tt class="xref std std-keyword docutils literal"><span class="pre">assert</span></tt> ）语句。使用 <em class="xref std std-option">-O</em> 参数， <em>所有</em> 的字节码（ <em class="xref std std-term">bytecode</em> ）都会被优化； <tt class="docutils literal"><span class="pre">.pyc</span></tt> 文件被忽略， <tt class="docutils literal"><span class="pre">.py</span></tt>  文件被编译为优化代码。</p>
</li>
<li><p class="first">向 Python 解释器传递两个 <em class="xref std std-option">-O</em> 参数（ <em class="xref std std-option">-OO</em> ）会执行完全优化的二进制优化编译，这偶尔会生成错误的程序。现在的优化器，只是从字节码中删除了 <tt class="docutils literal"><span class="pre">__doc__</span></tt> 符串，生成更为紧凑的 <tt class="file docutils literal"><span class="pre">.pyo</span></tt>  文件。因为某些程序依赖于这些变量的可用性，你应该只在确定无误的场合使用这一选项。</p>
</li>
<li><p class="first">来自 <tt class="file docutils literal"><span class="pre">.pyc</span></tt> 文件或 <tt class="file docutils literal"><span class="pre">.pyo</span></tt> 文件中的程序不会比来自 <tt class="file docutils literal"><span class="pre">.py</span></tt> 文件的运行更快； <tt class="file docutils literal"><span class="pre">.pyc</span></tt> 或 <tt class="file docutils literal"><span class="pre">.pyo</span></tt> 文件只是在它们加载的时候更快一些。</p>
</li>
<li><p class="first">通过脚本名在命令行运行脚本时，不会将为该脚本创建的二进制代码写入 <tt class="file docutils literal"><span class="pre">.pyc</span></tt> 或 <tt class="file docutils literal"><span class="pre">.pyo</span></tt> 文件。当然，把脚本的主要代码移进一个模块里，然后用一个小的启动脚本导入这个模块，就可以提高脚本的启动速度。也可以直接在命令行中指定一个 <tt class="file docutils literal"><span class="pre">.pyc</span></tt> 或 <tt class="file docutils literal"><span class="pre">.pyo</span></tt> 文件。</p>
</li>
<li><p class="first">对于同一个模块（这里指例程 spam.py －－译者），可以只有 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> 文件（或者 <tt class="file docutils literal"><span class="pre">spam.pyc</span></tt> ，在使用 <em class="xref std std-option">-O</em> 参数时）而没有 <tt class="file docutils literal"><span class="pre">spam.py</span></tt>  文件。这样可以打包发布比较难于逆向工程的 Python 代码库。</p>
</li>
<li id="index-4"><p class="first"><tt class="xref py py-mod docutils literal"><span class="pre">compileall</span></tt> 模块可以为指定目录中的所有模块创建 <tt class="file docutils literal"><span class="pre">.pyc</span></tt> 文件（或者使用 <em class="xref std std-option">-O</em> 参数创建 <tt class="file docutils literal"><span class="pre">.pyo</span></tt> 文件）。</p>
</li>
</ul>
</div>
</div>
<div class="section" id="tut-standardmodules">
<span id="id6"></span><h2>6.2. 标准模块<a class="headerlink" href="#tut-standardmodules" title="Permalink to this headline">¶</a></h2>
<p id="index-5">Python 带有一个标准模块库，并发布有独立的文档，名为 Python 库参考手册（此后称其为“库参考手册”）。有一些模块内置于解释器之中，这些操作的访问接口不是语言内核的一部分，但是已经内置于解释器了。这既是为了提高效率，也是为了给系统调用等操作系统原生访问提供接口。这类模块集合是一个依赖于底层平台的配置选项。例如，<tt class="xref py py-mod docutils literal"><span class="pre">winreg</span></tt> 模块只提供在 Windows 系统上才有。有一个具体的模块值得注意： <tt class="xref py py-mod docutils literal"><span class="pre">sys</span></tt> ，这个模块内置于所有的 Python 解释器。变量 <tt class="docutils literal"><span class="pre">sys.ps1</span></tt> 和 <tt class="docutils literal"><span class="pre">sys.ps2</span></tt> 定义了主提示符和辅助提示符字符串:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">ps1</span>
<span class="go">&#39;&gt;&gt;&gt; &#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">ps2</span>
<span class="go">&#39;... &#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">ps1</span> <span class="o">=</span> <span class="s">&#39;C&gt; &#39;</span>
<span class="go">C&gt; print(&#39;Yuck!&#39;)</span>
<span class="go">Yuck!</span>
<span class="go">C&gt;</span>
</pre></div>
</div>
<p>这两个变量只在解释器的交互模式下有意义。</p>
<p>变量 <tt class="docutils literal"><span class="pre">sys.path</span></tt> 是解释器模块搜索路径的字符串列表。它由环境变量 <span class="target" id="index-6"></span><tt class="xref std std-envvar docutils literal"><span class="pre">PYTHONPATH</span></tt>  初始化，如果没有设定 <span class="target" id="index-7"></span><tt class="xref std std-envvar docutils literal"><span class="pre">PYTHONPATH</span></tt> ，就由内置的默认值初始化。你可以用标准的字符串操作修改它:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;/ufs/guido/lib/python&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="dir">
<span id="tut-dir"></span><h2>6.3. <tt class="xref py py-func docutils literal"><span class="pre">dir()</span></tt> 函数<a class="headerlink" href="#dir" title="Permalink to this headline">¶</a></h2>
<p>内置函数 <tt class="xref py py-func docutils literal"><span class="pre">dir()</span></tt> 用于按模块名搜索模块定义，它返回一个字符串类型的存储列表:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span><span class="o">,</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">fibo</span><span class="p">)</span>
<span class="go">[&#39;__name__&#39;, &#39;fib&#39;, &#39;fib2&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">sys</span><span class="p">)</span>
<span class="go">[&#39;__displayhook__&#39;, &#39;__doc__&#39;, &#39;__excepthook__&#39;, &#39;__name__&#39;, &#39;__stderr__&#39;,</span>
<span class="go"> &#39;__stdin__&#39;, &#39;__stdout__&#39;, &#39;_getframe&#39;, &#39;api_version&#39;, &#39;argv&#39;,</span>
<span class="go"> &#39;builtin_module_names&#39;, &#39;byteorder&#39;, &#39;callstats&#39;, &#39;copyright&#39;,</span>
<span class="go"> &#39;displayhook&#39;, &#39;exc_info&#39;, &#39;excepthook&#39;,</span>
<span class="go"> &#39;exec_prefix&#39;, &#39;executable&#39;, &#39;exit&#39;, &#39;getdefaultencoding&#39;, &#39;getdlopenflags&#39;,</span>
<span class="go"> &#39;getrecursionlimit&#39;, &#39;getrefcount&#39;, &#39;hexversion&#39;, &#39;maxint&#39;, &#39;maxunicode&#39;,</span>
<span class="go"> &#39;meta_path&#39;, &#39;modules&#39;, &#39;path&#39;, &#39;path_hooks&#39;, &#39;path_importer_cache&#39;,</span>
<span class="go"> &#39;platform&#39;, &#39;prefix&#39;, &#39;ps1&#39;, &#39;ps2&#39;, &#39;setcheckinterval&#39;, &#39;setdlopenflags&#39;,</span>
<span class="go"> &#39;setprofile&#39;, &#39;setrecursionlimit&#39;, &#39;settrace&#39;, &#39;stderr&#39;, &#39;stdin&#39;, &#39;stdout&#39;,</span>
<span class="go"> &#39;version&#39;, &#39;version_info&#39;, &#39;warnoptions&#39;]</span>
</pre></div>
</div>
<p>无参数调用时， <tt class="xref py py-func docutils literal"><span class="pre">dir()</span></tt> 函数返回当前定义的命名:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span> <span class="o">=</span> <span class="n">fibo</span><span class="o">.</span><span class="n">fib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">()</span>
<span class="go">[&#39;__builtins__&#39;, &#39;__doc__&#39;, &#39;__file__&#39;, &#39;__name__&#39;, &#39;a&#39;, &#39;fib&#39;, &#39;fibo&#39;, &#39;sys&#39;]</span>
</pre></div>
</div>
<p>注意该列表列出了所有类型的名称：变量，模块，函数，等等。</p>
<p id="index-8"><tt class="xref py py-func docutils literal"><span class="pre">dir()</span></tt> 不会列出内置函数和变量名。如果你想列出这些内容，它们在标准模块 <tt class="xref py py-mod docutils literal"><span class="pre">__builtin__</span></tt> 中定义:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">builtins</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">builtins</span><span class="p">)</span>

<span class="go">[&#39;ArithmeticError&#39;, &#39;AssertionError&#39;, &#39;AttributeError&#39;, &#39;BaseException&#39;, &#39;Buffer</span>
<span class="go">Error&#39;, &#39;BytesWarning&#39;, &#39;DeprecationWarning&#39;, &#39;EOFError&#39;, &#39;Ellipsis&#39;, &#39;Environme</span>
<span class="go">ntError&#39;, &#39;Exception&#39;, &#39;False&#39;, &#39;FloatingPointError&#39;, &#39;FutureWarning&#39;, &#39;Generato</span>
<span class="go">rExit&#39;, &#39;IOError&#39;, &#39;ImportError&#39;, &#39;ImportWarning&#39;, &#39;IndentationError&#39;, &#39;IndexErr</span>
<span class="go">or&#39;, &#39;KeyError&#39;, &#39;KeyboardInterrupt&#39;, &#39;LookupError&#39;, &#39;MemoryError&#39;, &#39;NameError&#39;,</span>
<span class="go"> &#39;None&#39;, &#39;NotImplemented&#39;, &#39;NotImplementedError&#39;, &#39;OSError&#39;, &#39;OverflowError&#39;, &#39;P</span>
<span class="go">endingDeprecationWarning&#39;, &#39;ReferenceError&#39;, &#39;RuntimeError&#39;, &#39;RuntimeWarning&#39;, &#39;</span>
<span class="go">StopIteration&#39;, &#39;SyntaxError&#39;, &#39;SyntaxWarning&#39;, &#39;SystemError&#39;, &#39;SystemExit&#39;, &#39;Ta</span>
<span class="go">bError&#39;, &#39;True&#39;, &#39;TypeError&#39;, &#39;UnboundLocalError&#39;, &#39;UnicodeDecodeError&#39;, &#39;Unicod</span>
<span class="go">eEncodeError&#39;, &#39;UnicodeError&#39;, &#39;UnicodeTranslateError&#39;, &#39;UnicodeWarning&#39;, &#39;UserW</span>
<span class="go">arning&#39;, &#39;ValueError&#39;, &#39;Warning&#39;, &#39;ZeroDivisionError&#39;, &#39;__build_class__&#39;, &#39;__deb</span>
<span class="go">ug__&#39;, &#39;__doc__&#39;, &#39;__import__&#39;, &#39;__name__&#39;, &#39;__package__&#39;, &#39;abs&#39;, &#39;all&#39;, &#39;any&#39;,</span>
<span class="go">&#39;ascii&#39;, &#39;bin&#39;, &#39;bool&#39;, &#39;bytearray&#39;, &#39;bytes&#39;, &#39;chr&#39;, &#39;classmethod&#39;, &#39;compile&#39;, &#39;</span>
<span class="go">complex&#39;, &#39;copyright&#39;, &#39;credits&#39;, &#39;delattr&#39;, &#39;dict&#39;, &#39;dir&#39;, &#39;divmod&#39;, &#39;enumerate</span>
<span class="go">&#39;, &#39;eval&#39;, &#39;exec&#39;, &#39;exit&#39;, &#39;filter&#39;, &#39;float&#39;, &#39;format&#39;, &#39;frozenset&#39;, &#39;getattr&#39;,</span>
<span class="go">&#39;globals&#39;, &#39;hasattr&#39;, &#39;hash&#39;, &#39;help&#39;, &#39;hex&#39;, &#39;id&#39;, &#39;input&#39;, &#39;int&#39;, &#39;isinstance&#39;,</span>
<span class="go"> &#39;issubclass&#39;, &#39;iter&#39;, &#39;len&#39;, &#39;license&#39;, &#39;list&#39;, &#39;locals&#39;, &#39;map&#39;, &#39;max&#39;, &#39;memory</span>
<span class="go">view&#39;, &#39;min&#39;, &#39;next&#39;, &#39;object&#39;, &#39;oct&#39;, &#39;open&#39;, &#39;ord&#39;, &#39;pow&#39;, &#39;print&#39;, &#39;property&#39;</span>
<span class="go">, &#39;quit&#39;, &#39;range&#39;, &#39;repr&#39;, &#39;reversed&#39;, &#39;round&#39;, &#39;set&#39;, &#39;setattr&#39;, &#39;slice&#39;, &#39;sort</span>
<span class="go">ed&#39;, &#39;staticmethod&#39;, &#39;str&#39;, &#39;sum&#39;, &#39;super&#39;, &#39;tuple&#39;, &#39;type&#39;, &#39;vars&#39;, &#39;zip&#39;]</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-packages">
<span id="id7"></span><h2>6.4. 包<a class="headerlink" href="#tut-packages" title="Permalink to this headline">¶</a></h2>
<p>包通常是使用用“圆点模块名”的结构化模块命名空间。例如，名为 <tt class="xref py py-mod docutils literal"><span class="pre">A.B</span></tt> 的模块表示了名为 <tt class="docutils literal"><span class="pre">A</span></tt>  的包中名为 <tt class="docutils literal"><span class="pre">B</span></tt> 的子模块。正如同用模块来保存不同的模块架构可以避免全局变量之间的相互冲突，使用圆点模块名保存像 NumPy 或 Python Imaging Library 之类的不同类库架构可以避免模块之间的命名冲突。</p>
<p>假设你现在想要设计一个模块集（一个“包”）来统一处理声音文件和声音数据。存在几种不同的声音格式（通常由它们的扩展名来标识，例如： <tt class="file docutils literal"><span class="pre">.wav</span></tt>,
<tt class="file docutils literal"><span class="pre">.aiff</span></tt>, <tt class="file docutils literal"><span class="pre">.au</span></tt> ），于是，为了在不同类型的文件格式之间转换，你需要维护一个不断增长的包集合。可能你还想要对声音数据做很多不同的操作（例如混音，添加回声，应用平衡 功能，创建一个人造效果），所以你要加入一个无限流模块来执行这些操作。你的包可能会是这个样子（通过分级的文件体系来进行分组）:</p>
<div class="highlight-python"><div class="highlight"><pre>sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...
</pre></div>
</div>
<p>当导入这个包时，Python 通过 <tt class="docutils literal"><span class="pre">sys.path</span></tt> 搜索路径查找包含这个包的子目录。</p>
<p>为了让 Python 将目录当做内容包，目录中必须包含 <tt class="file docutils literal"><span class="pre">__init__.py</span></tt> 文件。 这是为了避免一个含有烂俗名字的目录无意中隐藏了稍后在模块搜索路径中出现的有效模块，比如 string 。 最简单的情况下，只需要一个空的 <tt class="file docutils literal"><span class="pre">__init__.py</span></tt> 文件即可。 当然它也可以执行包的初始化代码，或者定义稍后介绍的 <tt class="docutils literal"><span class="pre">__all__</span></tt> 变量。</p>
<p>用户可以每次只导入包里的特定模块，例如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sound.effects.echo</span>
</pre></div>
</div>
<p>这样就导入了 <tt class="xref py py-mod docutils literal"><span class="pre">sound.effects.echo</span></tt> 子模块。它必需通过完整的名称来引用。</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">sound</span><span class="o">.</span><span class="n">effects</span><span class="o">.</span><span class="n">echo</span><span class="o">.</span><span class="n">echofilter</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">atten</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>导入包时有一个可以选择的方式:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sound.effects</span> <span class="kn">import</span> <span class="n">echo</span>
</pre></div>
</div>
<p>这样就加载了 <tt class="xref py py-mod docutils literal"><span class="pre">echo</span></tt> 子模块，并且使得它在没有包前缀的情况下也可以使用，所以它可以如下方式调用</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">echo</span><span class="o">.</span><span class="n">echofilter</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">atten</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>还有另一种变体用于直接导入函数或变量:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sound.effects.echo</span> <span class="kn">import</span> <span class="n">echofilter</span>
</pre></div>
</div>
<p>这样就又一次加载了 <tt class="xref py py-mod docutils literal"><span class="pre">echo</span></tt> 子模块，但这样就可以直接调用它的 <tt class="xref py py-func docutils literal"><span class="pre">echofilter()</span></tt> 函数:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">echofilter</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">atten</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>需要注意的是使用 <tt class="docutils literal"><span class="pre">from</span> <span class="pre">package</span> <span class="pre">import</span> <span class="pre">item</span></tt> 方式导入包时，这个子项（item）既可以是包中的一个子模块（或一个子包），也可以是包中定义的其它命名，像函数、类或变量。<tt class="docutils literal"><span class="pre">import</span></tt> 语句首先核对是否包中有这个子项，如果没有，它假定这是一个模块，并尝试加载它。如果没有找到它，会引发一个  <tt class="xref py py-exc docutils literal"><span class="pre">ImportError</span></tt> 异常。</p>
<p>相反，使用类似 <tt class="docutils literal"><span class="pre">import</span> <span class="pre">item.subitem.subsubitem</span></tt> 这样的语法时，这些子项必须是包，最后的子项可以是包或模块，但不能是前面子项中定义的类、函数或变量。</p>
<div class="section" id="tut-pkg-import-star">
<span id="id8"></span><h3>6.4.1. 从 * 导入包<a class="headerlink" href="#tut-pkg-import-star" title="Permalink to this headline">¶</a></h3>
<p id="index-9">那么当用户写下 <tt class="docutils literal"><span class="pre">from</span> <span class="pre">sound.Effects</span> <span class="pre">import</span> <span class="pre">*</span></tt> 时会发生什么事？理想中，总是希望在文件系统中找出包中所有的子模块，然后导入它们。这可能会花掉委有长时间，并且出现期待之外的边界效应，导出了希望只能显式导入的包。</p>
<p>对于包的作者来说唯一的解决方案就是给提供一个明确的包索引。 <tt class="xref std std-keyword docutils literal"><span class="pre">import</span></tt>  语句按如下条件进行转换：执行 <tt class="docutils literal"><span class="pre">from</span> <span class="pre">package</span> <span class="pre">import</span> <span class="pre">*</span></tt> 时，如果包中的 <tt class="file docutils literal"><span class="pre">__init__.py</span></tt> 代码定义了一个名为 <tt class="docutils literal"><span class="pre">__all__</span></tt> 的列表，就会按照列表中给出的模块名进行导入。新版本的包发布时作者可以任意更新这个列表。如果包作者不想 import * 的时候导入他们的包中所有模块，那么也可能会决定不支持它（ import * ）。例如， <tt class="file docutils literal"><span class="pre">sounds/effects/__init__.py</span></tt> 这个文件可能包括如下代码:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;echo&quot;</span><span class="p">,</span> <span class="s">&quot;surround&quot;</span><span class="p">,</span> <span class="s">&quot;reverse&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>这意味着 <tt class="docutils literal"><span class="pre">from</span> <span class="pre">Sound.Effects</span> <span class="pre">import</span> <span class="pre">*</span></tt> 语句会从 <tt class="xref py py-mod docutils literal"><span class="pre">sound</span></tt> 包中导入以上三个已命名的子模块。</p>
<p>如果没有定义 <tt class="docutils literal"><span class="pre">__all__</span></tt> ， <tt class="docutils literal"><span class="pre">from</span> <span class="pre">Sound.Effects</span> <span class="pre">import</span> <span class="pre">*</span></tt> 语句 <em>不会</em> 从 <tt class="xref py py-mod docutils literal"><span class="pre">sound.effects</span></tt> 包中导入所有的子模块。无论包中定义多少命名，只能确定的是导入了 <tt class="xref py py-mod docutils literal"><span class="pre">sound.effects</span></tt>  包（可能会运行 <tt class="file docutils literal"><span class="pre">__init__.py</span></tt> 中的初始化代码）以及包中定义的所有命名会随之导入。这样就从 <tt class="file docutils literal"><span class="pre">__init__.py</span></tt> 中导入了每一个命名（以及明确导入的子模块）。同样也包括了前述的 <tt class="xref std std-keyword docutils literal"><span class="pre">import</span></tt> 语句从包中明确导入的子模块，考虑以下代码:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sound.effects.echo</span>
<span class="kn">import</span> <span class="nn">sound.effects.surround</span>
<span class="kn">from</span> <span class="nn">sound.effects</span> <span class="kn">import</span> <span class="o">*</span>
</pre></div>
</div>
<p>在这个例子中， <tt class="xref py py-mod docutils literal"><span class="pre">echo</span></tt> 和 <tt class="xref py py-mod docutils literal"><span class="pre">surround</span></tt> 模块导入了当前的命名空间，这是因为执行 <tt class="docutils literal"><span class="pre">from...import</span></tt> 语句时它们已经定义在 <tt class="xref py py-mod docutils literal"><span class="pre">sound.effects</span></tt> 包中了（定义了 <tt class="docutils literal"><span class="pre">__all__</span></tt> 时也会同样工作）。</p>
<p>尽管某些模块设计为使用 <tt class="docutils literal"><span class="pre">import</span> <span class="pre">*</span></tt> 时它只导出符全某种模式的命名，仍然不建议在生产代码中使用这种写法。</p>
<p>记住， <tt class="docutils literal"><span class="pre">from</span> <span class="pre">Package</span> <span class="pre">import</span> <span class="pre">specific_submodule</span></tt>  没有错误！事实上，除非导入的模块需要使用其它包中的同名子模块，否则这是推荐的写法。</p>
</div>
<div class="section" id="id9">
<h3>6.4.2. 包内引用<a class="headerlink" href="#id9" title="Permalink to this headline">¶</a></h3>
<p>如果包中使用了子包结构（就像示例中的 <tt class="xref py py-mod docutils literal"><span class="pre">sound</span></tt>  包），可以按绝对位置从相邻的包中引入子模块。例如，如果 <tt class="xref py py-mod docutils literal"><span class="pre">sound.filters.vocoder</span></tt> 包需要使用 <tt class="xref py py-mod docutils literal"><span class="pre">sound.effects</span></tt> 包中的 <tt class="xref py py-mod docutils literal"><span class="pre">echo</span></tt> 模块，它可以 <tt class="docutils literal"><span class="pre">from</span> <span class="pre">Sound.Effects</span> <span class="pre">import</span> <span class="pre">echo</span></tt> 。</p>
<p>你可以用这样的形式 <tt class="docutils literal"><span class="pre">from</span> <span class="pre">module</span> <span class="pre">import</span> <span class="pre">name</span></tt> 来写显式的相对位置导入。那些显式相对导入用点号标明关联导入当前和上级包。以 <tt class="xref py py-mod docutils literal"><span class="pre">surround</span></tt> 模块为例，你可以这样用:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">echo</span>
<span class="kn">from</span> <span class="nn">..</span> <span class="kn">import</span> <span class="n">formats</span>
<span class="kn">from</span> <span class="nn">..filters</span> <span class="kn">import</span> <span class="n">equalizer</span>
</pre></div>
</div>
<p>需要注意的是显式或隐式相对位置导入都基于当前模块的命名。因为主模块的名字总是 <tt class="docutils literal"><span class="pre">&quot;__main__&quot;</span></tt> ，Python 应用程序的主模块应该总是用绝对导入。</p>
</div>
<div class="section" id="id10">
<h3>6.4.3. 多重目录中的包<a class="headerlink" href="#id10" title="Permalink to this headline">¶</a></h3>
<p>包支持一个更为特殊的特性， <tt class="xref py py-attr docutils literal"><span class="pre">__path__</span></tt> 。 在包的 <tt class="file docutils literal"><span class="pre">__init__.py</span></tt> 文件代码执行之前，该变量初始化一个目录名列表。该变量可以修改，它作用于包中的子包和模块的搜索功能。</p>
<p>这个功能可以用于扩展包中的模块集，不过它不常用。</p>
<p class="rubric">Footnotes</p>
<table class="docutils footnote" frame="void" id="id11" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[1]</a></td><td>事实上函数定义既是“声明”又是“可执行体”；执行体由函数在模块全局语义表中的命名导入。</td></tr>
</tbody>
</table>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">6. 模块</a><ul>
<li><a class="reference internal" href="#tut-moremodules">6.1. 深入模块</a><ul>
<li><a class="reference internal" href="#tut-modulesasscripts">6.1.1. 作为脚本来执行模块</a></li>
<li><a class="reference internal" href="#tut-searchpath">6.1.2. 模块的搜索路径</a></li>
<li><a class="reference internal" href="#python">6.1.3. “编译的” Python 文件</a></li>
</ul>
</li>
<li><a class="reference internal" href="#tut-standardmodules">6.2. 标准模块</a></li>
<li><a class="reference internal" href="#dir">6.3. <tt class="docutils literal"><span class="pre">dir()</span></tt> 函数</a></li>
<li><a class="reference internal" href="#tut-packages">6.4. 包</a><ul>
<li><a class="reference internal" href="#tut-pkg-import-star">6.4.1. 从 * 导入包</a></li>
<li><a class="reference internal" href="#id9">6.4.2. 包内引用</a></li>
<li><a class="reference internal" href="#id10">6.4.3. 多重目录中的包</a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="datastructures.html"
                        title="previous chapter">5. 数据结构</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="inputoutput.html"
                        title="next chapter">7. 输入和输出</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="_sources/modules.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="inputoutput.html" title="7. 输入和输出"
             >next</a> |</li>
        <li class="right" >
          <a href="datastructures.html" title="5. 数据结构"
             >previous</a> |</li>
        <li><a href="index.html">Python tutorial 3.4 documentation</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
        &copy; Copyright 2013, D.D.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.1.
    </div>
  </body>
</html>